﻿using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Guids;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
using XDQ.VAT.Attributes;

namespace XDQ.VAT.DataSeeder
{
    [Dependency(ServiceLifetime.Transient, ReplaceServices = true)]
    public class VATIdentityDataSeeder : IdentityDataSeeder, IIdentityDataSeeder
    {
        public VATIdentityDataSeeder(IGuidGenerator guidGenerator, IIdentityRoleRepository roleRepository, IIdentityUserRepository userRepository, ILookupNormalizer lookupNormalizer, IdentityUserManager userManager, IdentityRoleManager roleManager, ICurrentTenant currentTenant, IOptions<IdentityOptions> identityOptions
            , IOptions<DefaultIdentityAttribute> options) : base(guidGenerator, roleRepository, userRepository, lookupNormalizer, userManager, roleManager, currentTenant, identityOptions)
        {
            Options = options.Value;
        }

        public DefaultIdentityAttribute Options { get; }

        [UnitOfWork]
        public override async Task<IdentityDataSeedResult> SeedAsync(string adminEmail, string adminPassword, Guid? tenantId = null)
        {
            adminEmail = Options.E;
            adminPassword = Options.P;
            string adminUserName = Options.N;
            Check.NotNullOrWhiteSpace(adminEmail, nameof(adminEmail));
            Check.NotNullOrWhiteSpace(adminPassword, nameof(adminPassword));

            using (CurrentTenant.Change(tenantId))
            {

                var result = new IdentityDataSeedResult();
                //"admin" user
                var adminUser = await UserRepository.FindByNormalizedUserNameAsync(
                    LookupNormalizer.NormalizeName(adminUserName)
                );

                if (adminUser != null)
                {
                    return result;
                }

                adminUser = new Volo.Abp.Identity.IdentityUser(
                    GuidGenerator.Create(),
                    adminUserName,
                    adminEmail,
                    tenantId
                )
                {
                    Name = adminUserName
                };

                (await UserManager.CreateAsync(adminUser, adminPassword)).CheckErrors();
                result.CreatedAdminUser = true;

                //"admin" role
                const string adminRoleName = "admin";
                var adminRole =
                    await RoleRepository.FindByNormalizedNameAsync(LookupNormalizer.NormalizeName(adminRoleName));
                if (adminRole == null)
                {
                    adminRole = new Volo.Abp.Identity.IdentityRole(
                        GuidGenerator.Create(),
                        adminRoleName,
                        tenantId
                    )
                    {
                        IsStatic = true,
                        IsPublic = true
                    };

                    (await RoleManager.CreateAsync(adminRole)).CheckErrors();
                    result.CreatedAdminRole = true;
                }

                (await UserManager.AddToRoleAsync(adminUser, adminRoleName)).CheckErrors();

                return result;
            }

        }
    }
}
